;;;;
;;;;根据实体XML文件生成JAVA SSH框架中的数据层、业务层、ACTION层的文件
;;;;并生成配置文件，测试用文件
;;;;


;;;定义常量
(defvar *from-dir* "/data/workspace/cblink4/")
(defvar *to-dir* "/data/workspace/cblink6/")
(defvar *model-dir* "/src/com/cblink/persistent/model/*.xml")
(defvar *dao-dir* "/src/com/cblink/persistent/dao/")
(defvar *dao-impl-dir* "/src/com/cblink/persistent/dao/impl/")
(defvar *biz-dir* "/src/com/cblink/biz/")
(defvar *biz-impl-dir* "/src/com/cblink/biz/impl/")
(defvar *action-dir* "/src/com/cblink/web/action/")

(defun find-table-name (path)
  "从实体的XML文件中提取表名、ID、字段名及类型"
  (let ((files (directory path))
	(tables (make-hash-table)))
    (dolist (file files)
      (let* ((filename (file-namestring file))
	     (table-name (subseq filename 0 (- (length filename) 8)))
	     (fields (make-hash-table))
	     (id nil)
	     (pre-line nil))
	;(format t "~A~%" table-name)
	(with-open-file (stream file)
	  (loop for line = (read-line stream nil 'end)
	     until (eq line 'end)
	     do (if (= -1 (is-find "column name" line))
		    (setf pre-line line)
		    (if (> (is-find "name=" pre-line) 0)
			(multiple-value-bind (isid field type)
			    (analyze-line line pre-line)
			  ;(format t "~A ~A ~A~%" isid field type)
			  (if isid
			      (setf (gethash 'id fields) field)
			      (setf (gethash field fields) type)))))))
	(setf (gethash table-name tables) fields)))
    (values tables)))

(defun analyze-line (line pre-line)
  "根据行内容提取字段名及类型"
  (cond ((< -1 (is-find "id name" pre-line))
	 (values t (extract-field pre-line "name") 
		 (sub-field-type (extract-field pre-line "type"))))
	((< -1 (is-find "many-to-one" pre-line))
	 (values nil (extract-field pre-line "name") 
		 "String"))
	((< -1 (is-find "property" pre-line))
	 (values nil (extract-field pre-line "name") 
		 (sub-field-type (extract-field pre-line "type"))))))

(defun extract-field (line name)
  (multiple-value-bind (match regs)
      (cl-ppcre:scan-to-strings (concatenate 'string name "=\"(.*?)\"") line)
    (if (> (length regs) 0)
	(elt regs 0)
	"")))

(defun sub-field-type (type)
  (if type
      (subseq type (let ((pos (search "." type :from-end t)))
		     (if pos
			 (1+ pos)
			 0)))
      ""))

(defun is-find (word line)  (let ((pos (search word line)))
    (if (null pos)
	-1
	pos)))

(defun auto-make-java ()
  "主程序，生成需要的文件"
  (let* ((tables (find-table-name (concatenate 'string *from-dir* *model-dir*))))
    (loop for k being the hash-keys of tables 
	 using (hash-value v)
	 do
	 (format t "~A ~A ~%" k (gethash 'id v))
	 (remhash 'id v)
	 (maphash #'(lambda (k1 v1)
			(format t "~A ~A => ~A~%" k k1 v1)) v))))


(defun make-file (table-name id path filename)
  "根据模板生成文件"
  (let ((table-name-lowercase (string-downcase table-name)) 
	(id-first-upcase (string-upcase id :start 0 :end 1)))
    (with-open-file (to-file (concatenate *to-dir* path filename)
			     :direction :output)
      (with-open-file (stream (concatename *from-dir* path "template.java"))
	(do ((line (read-line stream nil)
		   (read-line stream nil)))
	    ((null line))
	  (write-line line to-file))))))


(make-file "Test" "tid" "/src/com/cblink/persistent/dao/" "Test.java")


;(auto-make-java)



